#include <restraint.t>
// =========== Body parts ==============

class defaultHairPart: ForcedPart 'hair/mane' 'hair'
;

class defaultEyePart: ForcedPart 'eyes/eyeballs' 'eyes'
	isPlural = true
;

class defaultNosePart: ForcedPart 'nose/nostrils' 'nose'
	isHole = true
;

class defaultMouthPart: ForcedPart 'mouth' 'mouth'
	isHole = true
;

class defaultLipPart: ForcedPart 'lips' 'lips'
	isPlural = true
;

class defaultToothPart: ForcedPart 'teeth/tooth' 'teeth'
	isPlural = true
;

class defaultTonguePart: ForcedPart 'tongue' 'tongue'
;

class defaultNeckPart: ForcedPart 'neck' 'neck'
;

class defaultHeadPart: ForcedPart 'head' 'head'
;

class defaultBackPart: ForcedPart 'back/backside' 'back'
;

class defaultArmPitPart: ForcedPart 'armpits/arm-pits/arm pits' 'arm-pits'
	isPlural = true
;

class defaultArmPitHairPart: ForcedPart 'armpit hair/arm-pit hair/arm pit hair' 'arm-pit hair'
;

class defaultBreastPart: ForcedPart 'breasts/boobs/tits' 'breasts'
	isPlural = true
;

class defaultNipplePart: defaultBreastPart 'nipples' 'nipples'
	isPlural = true
;

class defaultElbowPart: ForcedPart 'elbows' 'elbows'
	isPlural = true
;

class defaultWristPart: ForcedPart 'wrists' 'wrists'
	isPlural = true
;

class defaultHandPart: ForcedPart 'hands/palms' 'hands'
	isPlural = true
;

class defaultFingerPart: ForcedPart 'fingers' 'fingers'
	isPlural = true
;

class defaultWaistPart: ForcedPart 'waist' 'waist'
;

class defaultBellyPart: ForcedPart 'belly/solar plexus/navel/stomach' 'belly'
;

class defaultCrotchPart: ForcedPart 'crotch/vulva/mound' 'crotch'
;

class defaultButtockPart: ForcedPart 'butt/buttocks/ass/rear/bottom' 'buttocks'
	isPlural = true
;

class defaultPubesPart: ForcedPart 'crotch hair/pubes/pubic hair' 'pubes'
	isPlural = true
;

class defaultLabiaPart: defaultCrotchPart 'labia/inner lips/nether lips/sex lips' 'labia'
	isPlural = true
;

class defaultClitorisPart: defaultCrotchPart 'clitoris/clit' 'clitoris'
;

class defaultVaginaPart: defaultCrotchPart 'vagina/pussy/cunt/sex' 'vagina'
	isHole = true
;

class defaultUrethraPart: ForcedPart 'urethra/pee-hole' 'urethra'
	isHole = true
;

class defaultPenisPart: defaultCrotchPart 'penis/dick/cock/manhood/sex' 'penis'
;

class defaultTesticlePart: defaultCrotchPart 'testicles/balls/bollocks' 'testicles'
	isPlural = true
;

class defaultRectumPart: ForcedPart 'rectum/asshole/ass-hole/anus' 'rectum'
	isHole = true
;

class defaultKneePart: ForcedPart 'knees' 'knees'
	isPlural = true
;

class defaultAnklePart: ForcedPart 'ankles' 'ankles'
	isPlural = true
;

class defaultFootPart: ForcedPart 'feet/foot/soles' 'feet'
	isPlural = true
;

class defaultToePart: ForcedPart 'toes' 'toes'
	isPlural = true
;



// ============ Forced Persons ============

class ForcedPerson : Actor
	isGagged = nil
	isRapeable = nil
	isHelpless = nil
	bodyParts = nil
        accumPain = 0
        accumDamage = 0
	inventoryLister = restrainedInventoryLister
	holdingDescInventoryLister = restrainedHoldingDescInventoryListerLong

        dobjFor(Release) remapTo(ReleaseFrom,gDobj,location)
        dobjFor(ReleaseFrom)
        {
            action()
            {
                if(gIobj.ofKind(Restraint))
                    nestedActorAction(gDobj, Doff, gIobj);
            }
        }
    
	dobjFor(RestrainWith)
	{
		verify()
		{
		}
		check()
		{
			if(!gIobj.ofKind(Restraint) && !gIobj.ofKind(TortureFurniture) )
			{
				"That is not a restraint";
				exit;
			}	
		}
		action()
		{	
			"{You/he} put{s}  <<gIobj.theName>> on <<theName>>. ";
			gIobj.moveInto(self);
			gIobj.makeWornBy(self);	
		}
	}
	
	dobjFor(TortureWith)
	{
		verify()
		{
		}
		check()
		{
		}
		action()
		{	
		}
	}
    
    	dobjFor(RestrainTo)
	{
		verify()
		{
		}
		check()
		{
		}
		action()
		{	
		}
	}

	dobjFor(Torture)
	{
		verify()
		{
		
		}
		check()
		{
			if(self.location.ofKind(TortureFurniture))
			{
				"(using <<self.location.theName>> as device)\n";
				replaceAction(TortureWith,self,self.location);
				return;
			}
		}
		action()
		{	
		}
	}

	restrainedBy(restrain)
	{
		local outstr ='';
		foreach(local b in bodyParts)
		{
			if(restrain.restrains(b))
				outstr += b.name+' ';
		}
		return outstr;
	} 

	restraintFactor(bodyPart)
	{
		local factor=1.00;
		foreach(local cur in contents)
            	{  
                	if(cur.ofKind(Restraint))
                	{
                        	if(cur.restrains(bodyPart))
                        	{  
                            	factor = factor * cur.hinderFactor;
                        	}
                	}
            	}
		return factor;
	}

	calculateSuccess( lstparts, lstdifficulty, obj,verb )
	{
	  local bestindex = 1;
	  local bestchances = -100;
	  local bestfactor = 0.0;
	  for (local i = 1 ; i <= lstparts.length() ; ++i)
	  {
	     local factor = restraintFactor(lstparts[i]);
	     if((factor*100)-lstdifficulty[i] > bestchances)
	     {
	       bestindex = i;
	       bestfactor = factor;
	       bestchances = (factor*100)-lstdifficulty[i];
	       " dbg: bestchances with <<lstparts[bestindex].name>> \n";
	     }
	  }
	  if(obj !=nil)
	  {
		device = nil;
		foreach(local cur in contents)
		{  
			if(cur.ofKind(Restraint))
			{
				if(cur.restrains(lstparts[bestindex]))
				{  
					device = cur;
					break;
				}
			}
		}
		obj.verbDescription(verb,lstparts[bestindex],device);
	  }
	  if(bestfactor == 1.0 )
	  {
	   //automatic success ?
	    return true;
	  }
	  if(bestfactor*100 < lstdifficulty[bestindex])
	  {
	      //impossible
	      foreach(local cur in contents)
	      {  
                	if(cur.ofKind(Restraint))
                	{
                        	if(cur.restrains(lstparts[bestindex]))
                        	{  
                            	cur.actionFailureDesc;
                        	}
                	}
	      }
	      " It's impossible. ";
	      return nil;
	  }
	  local randnumber = new BigNumber(rand(100),2);
	  " dbg: if <<randnumber*bestfactor>> less than <<lstdifficulty[bestindex]>> then fail \n";
	  if(randnumber*bestfactor < lstdifficulty[bestindex])
	  {
	    foreach(local cur in contents)
	      {  
                	if(cur.ofKind(Restraint))
                	{
                        	if(cur.restrains(lstparts[bestindex]))
                        	{  
                            	cur.actionFailureDesc;
                        	}
                	}
	      }
	      return nil;
	  }
	  else
	  {
	    foreach(local cur in contents)
	      {  
                	if(cur.ofKind(Restraint))
                	{
                        	if(cur.restrains(lstparts[bestindex]))
                        	{  
                            	cur.actionSuccessDesc;
                        	}
                	}
	      }
	      return true;
	  }
	}
	
	tortureReaction(part,device)
	{
		/*   device.painLevel and device.damageLevel can be used,
		*   as well as part.ofKind(defaultBreastPart) or device.ofKind(HitDevice)
		*   This function should be overwritten to give a per character reaction */
		if (device.ofKind(HitDevice))
			"A red welt appears on <<itPossAdj>> <<part.name>>. ";
		else if (device.ofKind(BurnDevice))
			"A blister appears on <<itPossAdj>> <<part.name>>. ";
		else if (device.ofKind(RapeDevice))
			"<<theName>> moans as <<itPossAdj>> <<part.name>> is forced. ";
		else if (device.ofKind(PressureDevice))
			"<<theName>> moans as <<itPossAdj>> <<part.name>> is pressured. ";
		else if (device.ofKind(ElectricDevice))
			"<<itPossAdj>> <<part.name>> is jerking and clenching uncontrollably. ";
		else if (device.ofKind(PierceDevice))
			"A trickle of blood appears around <<itPossAdj>> pierced <<part.name>>. ";
		else
			"<<theName>> gasps in pain. ";
	} 
	
	tortureFurnitureReaction(device)
	{
		/*   device.painLevel and device.damageLevel can be used,
		*   as well as part.ofKind(defaultBreastPart) or device.ofKind(HitDevice)
		*   This function should be overwritten to give a per character reaction */
		if (device.ofKind(RackDevice))
			"<<theName>> {are} stretched taut, <<itPossAdj>> muscles bulge as <<itNom>> tr{ies} to resist the traction. ";
		else
			"<<theName>> gasps in pain. ";
	} 
    
        addPainandDamage(pain,damage)
        {
            //this should be overridden for each person
        }
    
    reportAccumPain(){}
    reportAccumDamage(){}
    
        doRestraintEffect(restraint)
        {
            local pain = restraint.painLevel;
            local damage = restraint.damageLevel;
	addPainandDamage(pain,damage);
	/*maybe shuffellist of responses and only when pain reached certain level*/
	restraint.getEffectDescription();
        }
    
        doFurnitureEffect(device)
        {
            local pain = device.painLevel;
            local damage = device.damageLevel;
            addPainandDamage(pain,damage);
	    device.getEffectDescription();    
        }
;

class BasicForcedPerson: ForcedPerson
	fillDefaultParts()
	{
		bodyParts = new Vector(32);
		local eyes = new defaultEyePart;
		eyes.moveInto(self);

		bodyParts.append( eyes);
		local mouth= new defaultMouthPart;
		mouth.moveInto(self);
		bodyParts.append( mouth); 

		local wrists= new defaultWristPart;
		wrists.moveInto(self);
		bodyParts.append(wrists);

		local ankles= new defaultAnklePart;
		ankles.moveInto(self);
		bodyParts.append(ankles);

		local back = new defaultBackPart;
		back.moveInto(self);
		bodyParts.append(back);
	}
	initializeThing()
	{
		fillDefaultParts();
		inherited();
	}
;

class DetailedBoundPerson: BasicForcedPerson

	fillMaleParts()
	{
		local nipples = new defaultNipplePart;
		nipples.moveInto(self);
		bodyParts.append(nipples);

		local penis = new defaultPenisPart;
		penis.moveInto(self);
		bodyParts.append(penis);

		local testicles = new defaultTesticlePart;
		testicles.moveInto(self);
		bodyParts.append(testicles);

		local rectum = new defaultRectumPart;
		rectum.moveInto(self);
		bodyParts.append(rectum);
	}

	fillFemaleParts()
	{
		local neck = new defaultNeckPart;
		neck.moveInto(self);
		bodyParts.append(neck);
			
		local breast = new defaultBreastPart;
		breast.moveInto(self);
		bodyParts.append(breast);
			
		local nipples = new defaultNipplePart;
		nipples.moveInto(self);
		bodyParts.append(nipples);

		local labia = new defaultLabiaPart;
		labia.moveInto(self);
		bodyParts.append(labia);

		local clitoris = new defaultClitorisPart;
		clitoris.moveInto(self);
		bodyParts.append(clitoris);

		local vagina = new defaultVaginaPart;
		vagina.moveInto(self);
		bodyParts.append(vagina);

		local rectum = new defaultRectumPart;
		rectum.moveInto(self);
		bodyParts.append(rectum);
	}

	fillDefaultParts()
	{
		inherited();
		if(isHer)
			fillFemaleParts();
		else
			fillMaleParts();
		
		local head = new defaultHeadPart;
		head.moveInto(self);
		bodyParts.append(head);
		
		local nose = new defaultNosePart;
		nose.moveInto(self);
		bodyParts.append(nose);

		local tongue = new defaultTonguePart;
		tongue.moveInto(self);
		bodyParts.append(tongue);

		local elbows = new defaultElbowPart;
		elbows.moveInto(self);
		bodyParts.append(elbows);

		local fingers = new defaultFingerPart;
		fingers.moveInto(self);
		bodyParts.append(fingers);

		local waist = new defaultWaistPart;
		waist.moveInto(self);
		bodyParts.append(waist);

		local urethra = new defaultUrethraPart;
		urethra.moveInto(self);
		bodyParts.append(urethra);

		local knees = new defaultKneePart;
		knees.moveInto(self);
		bodyParts.append(knees);

		local toes = new defaultToePart;
		toes.moveInto(self);
		bodyParts.append(toes);
	}
;

class DetailedTorturedPerson: DetailedBoundPerson
	fillDefaultParts()
	{
		inherited();

		local hair = new defaultHairPart;
		hair.moveInto(self);
		bodyParts.append(hair);

		local teeth = new defaultToothPart;
		teeth.moveInto(self);
		bodyParts.append(teeth);

		local lips = new defaultLipPart;
		lips.moveInto(self);
		bodyParts.append(lips);

		local armpits = new defaultArmPitPart;
		armpits.moveInto(self);
		bodyParts.append(armpits);

		local hands = new defaultHandPart;
		hands.moveInto(self);
		bodyParts.append(hands);

		local belly = new defaultBellyPart;
		belly.moveInto(self);
		bodyParts.append(belly);

		local crotch = new defaultCrotchPart;
		crotch.moveInto(self);
		bodyParts.append(crotch);

		local buttocks = new defaultButtockPart;
		buttocks.moveInto(self);
		bodyParts.append(buttocks);

		local pubes = new defaultPubesPart;
		pubes.moveInto(self);
		bodyParts.append(pubes);

		local feet = new defaultFootPart;
		feet.moveInto(self);
		bodyParts.append(feet);
	}
;

class ForcedAgenda: AgendaItem
    initiallyActive = true
    agendaOrder = 1
    invokeItem() 
    {
       local actor = getActor();
       if(actor.ofKind(ForcedPerson))
       {
            foreach(local cur in actor.contents)
            {
                if(cur.ofKind(TortureRestraint))
                {
                        if(cur.isWorn())
                        {
                            actor.doRestraintEffect(cur);
                        }
                }
            }
            if(actor.location.ofKind(TortureFurniture))
            {
                actor.doFurnitureEffect(actor.location);
            }
            actor.reportAccumPain();
            actor.reportAccumDamage();
       }
       else
            isDone = true;
    }
;
